from rest_framework.views import APIView
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework import status
from orders.models import Order
from coupon.models import UserCoupon
from alipay import AliPay
from django.conf import settings
import os
from django.db import transaction
from decimal import Decimal
import logging
from datetime import datetime
from users.models import UserCourse

log = logging.getLogger('django')


# Create your views here.


class AlipayAPIView(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request):
        coupon_id = request.query_params.get('coupon_id')
        order_number = request.query_params.get('order_number')
        try:
            order = Order.objects.get(order_number=order_number)
        except Order.DoesNotExist:
            return Response({'message': '对不起，当前订单信息不存在！无法进行支付'}, status=status.HTTP_400_BAD_REQUEST)
        if order.real_price < 0:
            order.real_price = 0
            order.save()
        if order.real_price == 0:
            url = settings.ALIPAY_RETURN_URL + "?charset=utf-8&out_trade_no={}&timestamp={}".format(
                order_number, datetime.now())
            return Response({'message': '购买成功', 'url': url})
        if coupon_id != None and coupon_id != '0':
            with transaction.atomic():
                save_id = transaction.savepoint()
                try:
                    user_coupon = UserCoupon.objects.get(pk=coupon_id)
                except UserCoupon.DoesNotExist:
                    return Response({'message': '对不起，当前订单使用的优惠券不存在！无法进行支付'}, status=status.HTTP_400_BAD_REQUEST)
                if user_coupon.coupon.coupon_type == 0:
                    order.real_price = order.total_price * Decimal(user_coupon.coupon.sale[1:])
                elif user_coupon.coupon.coupon_type == 1:
                    order.real_price = order.total_price - Decimal(user_coupon.coupon.sale[1:])
                    if order.real_price <= 0:
                        order.real_price = 0
                        order.save()
                        url = settings.ALIPAY_RETURN_URL + "?charset=utf-8&out_trade_no={}&timestamp={}".format(
                            order_number, datetime.now())
                        return Response({'message': '购买成功', 'url': url})
                else:
                    return Response({"message": '当前优惠券无法使用！无法进行支付'}, status=status.HTTP_400_BAD_REQUEST)

                try:
                    order.user_coupon = True
                    order.coupon = user_coupon.id
                    order.save()
                    user_coupon.is_use = True
                    user_coupon.save()
                except:
                    transaction.savepoint_rollback(save_id)
                    return Response({'message': '系统异常，无法进行支付'}, status=status.HTTP_400_BAD_REQUEST)

        alipay = AliPay(
            appid=settings.ALIPAY_APPID,
            app_notify_url=settings.ALIPAY_APP_NOTIFY_URL,
            app_private_key_path=os.path.join(os.path.dirname(os.path.abspath(__file__)), 'keys/app_private_key.pem'),
            alipay_public_key_path=os.path.join(os.path.dirname(os.path.abspath(__file__)),
                                                'keys/alipay_public_key.pem'),
            sign_type='RSA2',
            debug=settings.ALIPAY_DEBUG,
        )
        order_string = alipay.api_alipay_trade_page_pay(
            out_trade_no=order.order_number,
            total_amount='%.2f' % order.real_price,
            subject=order.order_title,
            return_url=settings.ALIPAY_RETURN_URL,
            notify_url=settings.ALIPAY_NOTIFY_URL,
        )
        url = settings.APIPAY_GATEWAY + '?' + order_string
        return Response({'message': '发起支付成功', 'url': url})


class AlipayResultAPIView(APIView):
    def get(self, request):
        data = request.query_params.dict()
        if data.get('sign', None):
            signature = data.pop('sign')
            alipay = AliPay(
                appid=settings.ALIPAY_APPID,
                app_notify_url=settings.ALIPAY_APP_NOTIFY_URL,
                app_private_key_path=os.path.join(os.path.dirname(os.path.abspath(__file__)),
                                                  'keys/app_private_key.pem'),
                alipay_public_key_path=os.path.join(os.path.dirname(os.path.abspath(__file__)),
                                                    'keys/alipay_public_key.pem'),
                sign_type='RSA2',
                debug=settings.ALIPAY_DEBUG,
            )
            success = alipay.verify(data, signature)
            if not success:
                return
        order_number = data.get('out_trade_no')
        try:
            order = Order.objects.get(order_number=order_number)
        except Order.DoesNotExist:
            log.error('订单号：{}不存在'.format(order_number))
            return Response({'message': '无效的订单号'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
        with transaction.atomic():
            save_id = transaction.savepoint()
            try:
                order.order_status = 1
                order.pay_time = datetime.now()
                order.save()
                detail_list = order.order_courses.all()
                course_list = []
                for detail in detail_list:
                    if detail.expire == -1:
                        out_time = '2199-12-31 23:59:59'
                    else:
                        out_time = datetime.now().timestamp() + detail.expire * 86400
                        out_time = datetime.fromtimestamp(out_time)
                        out_time = out_time.strftime('%Y-%m-%d %H:%M:%S')
                    UserCourse.objects.create(
                        user=order.user,
                        course=detail.course,
                        buy_number=data.get('trade_no'),
                        buy_type=0,
                        pay_time=data.get('timestamp'),
                        out_time=out_time,
                    )
                    course_list.append(detail.course.name)
                return Response({'message': {
                    'pay_time': order.pay_time.strftime('%Y-%m-%d %H:%M:%S'),
                    'real_price': order.real_price,
                    'course_list': course_list,
                }}, status=status.HTTP_200_OK)
            except:
                log.error('修改订单和购买记录发生异常')
                transaction.savepoint_rollback(save_id)
                return Response({'message': '系统异常'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    def post(self, request):
        data = request.data.dict()
        signature = data.pop('sign')
        alipay = AliPay(
            appid=settings.ALIPAY_APPID,
            app_notify_url=settings.ALIPAY_APP_NOTIFY_URL,
            app_private_key_path=os.path.join(os.path.dirname(os.path.abspath(__file__)), 'keys/app_private_key.pem'),
            alipay_public_key_path=os.path.join(os.path.dirname(os.path.abspath(__file__)),
                                                'keys/alipay_public_key.pem'),
            sign_type='RSA2',
            debug=settings.ALIPAY_DEBUG,
        )
        success = alipay.verify(data, signature)
        if success:
            order_number = data.get('out_trade_no')
            try:
                order = Order.objects.get(order_number=order_number)
            except Order.DoesNotExist:
                log.error('订单号：{}不存在'.format(order_number))
                return Response({'message': '无效的订单号'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
            with transaction.atomic():
                save_id = transaction.savepoint()
                try:
                    order.order_status = 1
                    order.pay_time = datetime.now()
                    order.save()
                    detail_list = order.order_courses.all()
                    course_list = []
                    for detail in detail_list:
                        if detail.expire == -1:
                            out_time = '2199-12-31 23:59:59'
                        else:
                            out_time = datetime.now().timestamp() + detail.expire * 86400
                            out_time = datetime.fromtimestamp(out_time)
                            out_time = out_time.strftime('%Y-%m-%d %H:%M:%S')
                        UserCourse.objects.create(
                            user=order.user,
                            course=detail.course,
                            buy_number=data.get('trade_no'),
                            buy_type=0,
                            pay_time=data.get('timestamp'),
                            out_time=out_time,
                        )
                        course_list.append(detail.course.name)
                    return Response('success', content_type='text/html')
                except:
                    log.error('修改订单和购买记录发生异常')
                    transaction.savepoint_rollback(save_id)
                    return Response({'message': '系统异常'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
